#ifndef frm_control_TScrollBar_H
#define frm_control_TScrollBar_H

#include "frm_control_TSplitter.h"
#include "frm_control_TButton.h"

namespace frm { namespace control {

////////////////////////////////////////////////////////////////////////////////

struct TScrollBarBegButton : public TButton 
{
protected:
  TScrollBarBegButton(TWindow &Window) : TButton(Window) {}
};
struct TScrollBarVertBegButton : public TScrollBarBegButton
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarVertBegButton(TWindow &Window) : TScrollBarBegButton(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};
struct TScrollBarHorzBegButton : public TScrollBarBegButton
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarHorzBegButton(TWindow &Window) : TScrollBarBegButton(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};

////////////////////////////////////////////////////////////////////////////////

struct TScrollBarBegPage : public TButton 
{
protected:
  TScrollBarBegPage(TWindow &Window) : TButton(Window) {}
};
struct TScrollBarVertBegPage : public TScrollBarBegPage
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarVertBegPage(TWindow &Window) : TScrollBarBegPage(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};
struct TScrollBarHorzBegPage : public TScrollBarBegPage
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarHorzBegPage(TWindow &Window) : TScrollBarBegPage(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};

////////////////////////////////////////////////////////////////////////////////

struct TScrollBarTrack : public TSplitter
{
protected:
  TScrollBarTrack(TWindow &Window,TSplitter::ESplit Split,TPanel *CResizePrev) : TSplitter(Window,Split,CResizePrev) {}
};
struct TScrollBarVertTrack : public TScrollBarTrack
{
  struct TStyle : public TSplitterHorz::TStyle
  {
    svl_Type(TSplitterHorz::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarVertTrack(TWindow &Window,TPanel *CResizePrev) 
  :TScrollBarTrack(Window,TSplitter::Horz,CResizePrev)
  {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};
struct TScrollBarHorzTrack : public TScrollBarTrack
{
  struct TStyle : public TSplitterVert::TStyle
  {
    svl_Type(TSplitterVert::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarHorzTrack(TWindow &Window,TPanel *CResizePrev) 
  :TScrollBarTrack(Window,TSplitter::Vert,CResizePrev)
  {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};

////////////////////////////////////////////////////////////////////////////////

struct TScrollBarEndPage : public TButton 
{
protected:
  TScrollBarEndPage(TWindow &Window) : TButton(Window) {}
};
struct TScrollBarVertEndPage : public TScrollBarEndPage
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarVertEndPage(TWindow &Window) : TScrollBarEndPage(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};
struct TScrollBarHorzEndPage : public TScrollBarEndPage
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarHorzEndPage(TWindow &Window) : TScrollBarEndPage(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};

////////////////////////////////////////////////////////////////////////////////

struct TScrollBarEndButton : public TButton 
{
protected:
  TScrollBarEndButton(TWindow &Window) : TButton(Window) {}
};
struct TScrollBarVertEndButton : public TScrollBarEndButton
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarVertEndButton(TWindow &Window) : TScrollBarEndButton(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};
struct TScrollBarHorzEndButton : public TScrollBarEndButton
{
  struct TStyle : public TButton::TStyle
  {
    svl_Type(TButton::TStyle)
    //
    void SetDefault();
  };
  //
  TScrollBarHorzEndButton(TWindow &Window) : TScrollBarEndButton(Window) {}
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
};

////////////////////////////////////////////////////////////////////////////////

struct TScrollBar : public TPanel
{
  enum EScroll { Vert = 0,Horz = 1 };

  struct TStyle : public TPanel::TStyle
  {
    TButton  ::TStyle  BegButton;
    TButton  ::TStyle  BegPage;
    TButton  ::TStyle  EndPage;
    TButton  ::TStyle  EndButton;
    int				   Weight;
    //
    TStyle(TSplitter::TStyle &Track) : track(Track) {}
    //
    virtual EScroll GetEScroll() = 0;
    void operator=(const TStyle &From){
		Border = From.Border;
		Filler = From.Filler;
		BegButton = From.BegButton;
		BegPage   = From.BegPage;
		EndButton = From.EndButton;
		EndPage   = From.EndPage;
		track     = From.track;
		Weight	  = From.Weight;
	}
	//
    virtual void SetFromParent(frm::TStyle *Parent);
    virtual svl::TInfoParam AddInfoTo(svl::TInfoParam Info);
    
  private:
    TSplitter::TStyle &track;
    friend TScrollBar;
  };
  struct TStyleVert : public TStyle
  {
    TSplitterHorz::TStyle Track;
    //
	TStyleVert() : TStyle(Track) {}
	//
	void SetDefault();
    //
    virtual EScroll GetEScroll() { return Vert;}
  };
  struct TStyleHorz : public TStyle
  {
    TSplitterVert::TStyle Track;
    //
	TStyleHorz() : TStyle(Track) {}
    //
	void SetDefault();
    //
    virtual EScroll GetEScroll() { return Horz;}
  };

  ////////////////////////////////////
  struct TEvents : public svl::TEvents
  {
    virtual void TEvents_AfterChangePosition(TI&I,TScrollBar &Sender,int OldVal,int NewVal) { TEvents *P = (TEvents*)I.GetPrev(); if (P) { P->TEvents_AfterChangePosition(I,Sender,OldVal,NewVal);} }
    virtual void TEvents_AfterScroll        (TI&I,TScrollBar &Sender,int NewPosition)       { TEvents *P = (TEvents*)I.GetPrev(); if (P) { P->TEvents_AfterScroll(I,Sender,NewPosition);} }
  };
  ////////////////////////////////////////////
  struct TEventsList : public svl::TEventsList
  {
    TEventsList() : svl::TEventsList(Default()) {}
    //
    void Link  (TEvents &V) { svl::TEventsList::Link  (V);}
    void Unlink(TEvents &V) { svl::TEventsList::Unlink(V);}
    //
    TEvents &Get() { return (TEvents&)svl::TEventsList::GetBot();}
    
  private:
    static TEvents &Default() { static TEvents E; return E;}
  }
  Events;
  //////////////
  struct TStyles
  {
    TStyleVert Vert;
    TStyleHorz Horz;
    //
    TStyles() 
    { 
		s[TScrollBar::Vert] = &Vert; Vert.SetDefault();
		s[TScrollBar::Horz] = &Horz; Horz.SetDefault();
    }
    //
    TStyle &Get(EScroll V) { return *s[V];}
    
  private:
    TStyle *s[2];
  };
  //
  TScrollBarBegButton *BegButton;
  TScrollBarBegPage   *BegPage;
  TScrollBarTrack     *Track;
  TScrollBarEndPage   *EndPage;
  TScrollBarEndButton *EndButton;
  
protected:
  TScrollBar(TWindow &Window,EScroll Scroll);
  
public:  
 ~TScrollBar();
  //
  TScrollBar &SetStyle(TStyle &V);
  //
  int  GetSize();
  void SetSize(int V = 15);
  //
  void SetIncrement(int V = 10) { increment = V;}
  //
  int  GetPosition   () { return position;}
  void SetPosition   (int V = 0);
  void UpdatePosition(int V);
  void UpdateDeltaPosition(int V) { UpdatePosition(position + V);}
  //
  void SetRange   (int V = 1000);
  void UpdateRange(int V);

private:
  void UpdateSplitterSize();
  //
  int PositionFromTrackPosition(int TrackPosition);
  int TrackPositionFromPosition(int Position);
  //
  int CalcPageSize();
  //
  void TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles);
  //
  struct TResizeScroll : public geometry::TOrdinate::TEvents
  {
    TScrollBar &sb; TResizeScroll(TScrollBar &V) : sb(V) {}
    virtual void TEvents_AfterChangeSize(geometry::TOrdinate &Sender,int OldVal,int NewVal);
  }
  resizeScroll; friend TResizeScroll;
  //
  struct TResizeBegPage : public geometry::TOrdinate::TEvents
  {
    TScrollBar &sb; TResizeBegPage(TScrollBar &V) : sb(V) {}
    virtual void TEvents_BeforeChangeSize(geometry::TOrdinate &Sender,int OldVal,int &NewVal);
  }
  resizeBegPage; friend TResizeBegPage;
  //
  struct TEvButton : public TButton::TEvents
  {
    TScrollBar &sb; TEvButton(TScrollBar &V) : sb(V) {}
    virtual void TEvents_AfterDown(TI &I,TButton &Sender);
  }
  evButton; friend TEvButton;
  //
  struct TEvPage : public TButton::TEvents
  {
    TScrollBar &sb; TEvPage(TScrollBar &V) : sb(V) {}
    virtual void TEvents_AfterDown(TI &I,TButton &Sender);
  }
  evPage; friend TEvPage;
  //
  EScroll scroll;
  int increment,range,position;
  //TStyle *style;
  svl_Except;
};

///////////////////////////////////////////////////////////////////////////////

struct TScrollBarVert : public TScrollBar
{
  struct TStyle : public TStyleVert
  {
	  
  };
  //
  TScrollBarVert(TWindow &Window) : TScrollBar(Window,Vert) {}
  //
  TScrollBarVert &SetStyle(TStyle &V) { TScrollBar::SetStyle(V); return *this;} 
};

///////////////////////////////////////////////////////////////////////////////

struct TScrollBarHorz : public TScrollBar
{
  struct TStyle : public TStyleHorz
  {
  };
  //
  TScrollBarHorz(TWindow &Window) : TScrollBar(Window,Horz) {}
  //
  TScrollBarHorz &SetStyle(TStyle &V) { TScrollBar::SetStyle(V); return *this;} 
};

///////////////////////////////////////////////////////////////////////////////
}}

#endif
